package pl.kaczmarz.audiosteganography;

import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.text.DefaultCaret;

class EncoderPanel extends JPanel {

	private JPanel inside = new JPanel();
	private FileChooser inputWaveFile;
	private FileChooser outputWaveFile;
	private FileChooser messageFile;
	private FileChooser keyFile;
	private JButton encode;

	public EncoderPanel() {
		inside.setLayout(new BoxLayout(inside, BoxLayout.Y_AXIS));
		setLayout(new BorderLayout());

		inputWaveFile = new WaveFileChooser(JFileChooser.OPEN_DIALOG, "Plik wejściowy audio", "Otwórz");
		outputWaveFile =  new WaveFileChooser(JFileChooser.SAVE_DIALOG, "Plik wyjściowy audio", "Otwórz");
		messageFile =  new FileChooser(JFileChooser.OPEN_DIALOG, "Plik wejściowy z wiadomością", "Otwórz");
		keyFile = new FileChooser(JFileChooser.SAVE_DIALOG, "Plik wyjściowy klucza", "Otwórz");
		encode = new JButton("Zakoduj wiadomość");

		inside.add(inputWaveFile);
		inside.add(messageFile);
		inside.add(outputWaveFile);
		inside.add(keyFile);
		inside.add(encode);

		add(inside, BorderLayout.NORTH);
	}

	public void addActionListener(JTextArea console, JProgressBar progress, ExecutorService executor) {
		encode.addActionListener(new EncodeButtonListener(console, progress, executor));
	}

	private class EncodeButtonListener implements ActionListener, PropertyChangeListener {

		private Encoder encoder;
		private JTextArea console;
		private JProgressBar progressBar;
		private ExecutorService executor;

		private Future<Encoder> future;

		public EncodeButtonListener(JTextArea console, JProgressBar progress, ExecutorService executor) {
			this.console = console;
			this.progressBar = progress;
			this.executor = executor;
		}

		@Override
		@SuppressWarnings("unchecked")
		public void actionPerformed(ActionEvent e) {

			if (future == null || future.isDone()) {
				console.append("\nDodano nowe zadanie.\n");

				encoder = new Encoder();
				encoder.setConsoleOut(console);
				encoder.addPropertyChangeListener(this);
				encoder.setInputFileName(inputWaveFile.getFileName());
				encoder.setOutputFileName(outputWaveFile.getFileName());
				encoder.setMessageFileName(messageFile.getFileName());
				encoder.setKeyFileName(keyFile.getFileName());

				future = (Future<Encoder>) executor.submit(encoder);
			}
		}

		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if ("progress".equals(evt.getPropertyName())) {
				int progress = (Integer) evt.getNewValue();
				progressBar.setValue(progress);
			}
		}
	}
}

class DecoderPanel extends JPanel {

	private JPanel inside = new JPanel();
	private FileChooser inputWaveFile;
	private FileChooser keyFile;
	private FileChooser messageFile;
	private JButton decode;

	public DecoderPanel() {
		inside.setLayout(new BoxLayout(inside, BoxLayout.Y_AXIS));
		setLayout(new BorderLayout());

		inputWaveFile = new WaveFileChooser(JFileChooser.OPEN_DIALOG, "Plik wejściowy audio", "Otwórz");
		keyFile =  new FileChooser(JFileChooser.OPEN_DIALOG, "Plik wejściowy klucza", "Otwórz");
		messageFile =  new FileChooser(JFileChooser.SAVE_DIALOG, "Plik wyjściowy wiadomości", "Otwórz");
		decode = new JButton("Dekoduj");

		inside.add(inputWaveFile);
		inside.add(keyFile);
		inside.add(messageFile);
		inside.add(decode);

		add(inside,  BorderLayout.NORTH);
	}

	public void addActionListener(JTextArea console, JProgressBar progress, ExecutorService executor) {
		decode.addActionListener(new DecodeButtonListener(console, progress, executor));
	}

	private class DecodeButtonListener implements ActionListener, PropertyChangeListener {

		private Decoder decoder;
		private ExecutorService executor;
		private JTextArea console;
		private JProgressBar progressBar;

		private Future<Decoder> future;

		public DecodeButtonListener(JTextArea console, JProgressBar progress, ExecutorService executor) {
			this.console = console;
			this.progressBar = progress;
			this.executor = executor;
		}

		@Override
		@SuppressWarnings("unchecked")
		public void actionPerformed(ActionEvent e) {

			if (future == null || future.isDone()) {
				decoder = new Decoder();
				decoder.setConsoleOut(console);
				decoder.addPropertyChangeListener(this);
				decoder.setInputFileName(inputWaveFile.getFileName());
				decoder.setOutputFileName(messageFile.getFileName());
				decoder.setKeyFileName(keyFile.getFileName());

				future = (Future<Decoder>) executor.submit(decoder);
			}
		}

		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if ("progress".equals(evt.getPropertyName())) {
				int progress = (Integer) evt.getNewValue();
				progressBar.setValue(progress);
			}
		}
	}
}

/**
 *
 * @author Pawel
 */
public class MainWindow extends JFrame {

	private JTabbedPane tabbedPane;
	private JTextArea console;
	private EncoderPanel encoderPanel;
	private DecoderPanel decoderPanel;
	private JProgressBar progress;
	private JMenuBar menuBar;
	private List<Image> icons;
	private AboutWindow about;

	private ExecutorService executor = Executors.newFixedThreadPool(1);

	public MainWindow() {

		tabbedPane = new JTabbedPane();
		console = new JTextArea();
		encoderPanel = new EncoderPanel();
		decoderPanel = new DecoderPanel();
		progress = new JProgressBar(0, 100);

		super.setTitle("AudioSteganography");
		this.setLocationRelativeTo(null);

		icons = new ArrayList<>();

		icons.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icon16.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icon32.png")));
		icons.add(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icon64.png")));

		this.setIconImages(icons);

		/* setup the menu */
		menuBar = new JMenuBar();

		JMenu fileMenu = new JMenu("Plik");
		JMenuItem closeItem = new JMenuItem("Zakończ");
		fileMenu.add(closeItem);

		closeItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});

		menuBar.add(fileMenu);

		JMenu helpMenu = new JMenu("Pomoc");
		JMenuItem aboutItem = new JMenuItem("O programie");
		helpMenu.add(aboutItem);

		about = new AboutWindow(this, icons);

		aboutItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				about.setVisible(true);
			}
		});

		menuBar.add(helpMenu);

		setJMenuBar(menuBar);

		// set autocroll for console
		DefaultCaret caret = (DefaultCaret) console.getCaret();
		caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		// text padding
		console.setMargin(new Insets(5, 5, 5, 5));

		tabbedPane.addTab("Kodowanie", encoderPanel);
		tabbedPane.addTab("Dekodowanie", decoderPanel);

		getContentPane().add(tabbedPane, BorderLayout.NORTH);
		getContentPane().add(new JScrollPane(console), BorderLayout.CENTER);
		getContentPane().add(progress, BorderLayout.SOUTH);

		progress.setStringPainted(true);

		encoderPanel.addActionListener(console, progress, executor);
		decoderPanel.addActionListener(console, progress, executor);

		this.setSize(480, 480);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
	}

	@Override
	public void setTitle(String title) {
		if (title == null || title.length() == 0) {
			super.setTitle("AudioSteganography");
		} else {
			super.setTitle(title + " - AudioSteganography");
		}
	}
}


class AboutWindow extends JDialog {

	private JPanel content;
	private JLabel aboutLabel;
	private static String about
			= "<html><h1>AudioSteganography 1.3</h1>\n"
			+ "<p>Aplikacja ukrywająca dane w kontenerze dźwiękowym metodą dołaczania echa.</p>\n"
			+ "<p>Program jest częścią pracy inżynierskiej.</p>\n"
			+ "<p><b>Dyplomant:</b> Paweł Kaczmarz</p>"
			+ "<p><b>Promotor:</b> Dr inż. Grzegorz Kozieł</p>"
			+ "<p>Politechnika Lubelska, Wydział Elektrotechniki i Informatyki</p>"
			+ "<p>2012</p>"
			+ "<p>&nbsp;</p>"
			+ "<p>Oprogramowanie open source</p>"
			+ "<p>http://code.google.com/p/audio-steganography/</p>"
			+ "<p>&nbsp;</p></html>";
	private JButton close;
	private JButton website;

	public AboutWindow(JFrame parent, List<Image> icons) {
		super(parent);
		setTitle("Informacje o programie");
		setIconImages(icons);
		setModalityType(ModalityType.APPLICATION_MODAL);
		setLocationRelativeTo(parent);

		content = new JPanel(new BorderLayout());
		content.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		add(content, BorderLayout.CENTER);

		close = new JButton("Zamknij");

		close.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
			}
		});

		JPanel helper = new JPanel(new BorderLayout());
		helper.add(close, BorderLayout.EAST);




		website = new JButton("Strona projektu");

		website.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					Desktop.getDesktop().browse(new URI("http://code.google.com/p/audio-steganography/"));
				} catch (IOException | URISyntaxException ex) {
					// do not react
				}
			}
		});

		helper.add(website, BorderLayout.WEST);

		content.add(helper, BorderLayout.SOUTH);

		aboutLabel = new JLabel(about);
		aboutLabel.setText(about);
		content.add(aboutLabel, BorderLayout.CENTER);

		pack();
		setResizable(false);
	}
}

